#pragma once

#include "ISceneNode.h"

#include "..\Math\Matrix4x4.h"

#include "RayCast.h"

typedef std::vector<shared_ptr<ISceneNode> > SceneNodeList;

class SceneNode : public ISceneNode
{
	friend class Scene;

protected:
	
	SceneNodeList			m_Children;
	SceneNode				*m_pParent;
	SceneNodeProperties		m_Props;

public:
	SceneNode(
		ActorId actorId, 
		RenderPass renderPass, 
		const Matrix4x4 *to, 
		const Matrix4x4 *from=NULL);

	virtual ~SceneNode();

	virtual const SceneNodeProperties* const VGet() const { return &m_Props; }

	virtual void VSetTransform(const Matrix4x4 *toWorld, const Matrix4x4 *fromWorld=NULL);

	virtual HRESULT VOnRestore(Scene *pScene);
	virtual HRESULT VOnUpdate(Scene *, DWORD const elapsedMs);

	virtual HRESULT VPreRender(Scene *pScene);
	virtual bool VIsVisible(Scene *pScene) const;
	virtual HRESULT VRender(Scene *pScene) { return S_OK; } 
	virtual HRESULT VRenderChildren(Scene *pScene);
	virtual HRESULT VPostRender(Scene *pScene);

	virtual bool VAddChild(shared_ptr<ISceneNode> kid);
	virtual bool VRemoveChild(ActorId id);
	virtual HRESULT VOnLostDevice(Scene *pScene);
	virtual HRESULT VPick(Scene *pScene, RayCast *pRayCast);

	void SetAlpha(float alpha);
	float GetAlpha() const { return m_Props.Alpha(); }

	Vector3 GetPosition() const { return m_Props._toWorld.GetPosition(); }
	void SetPosition(const Vector3 &pos) { m_Props._toWorld.SetPosition(pos); }

	const Vector3 GetWorldPosition() const;					// [mrmike] added post-press to respect ancestor's position 

	Vector3 GetDirection() const { return m_Props._toWorld.GetDirection(); }

	void SetRadius(const float radius) { m_Props._radius = radius; }
	void SetMaterial(const Material &mat) { m_Props._material = mat; }
};